package jobs

import (
	"fmt"
	"gin_template/core/redis"
	"gin_template/core/setting"
	timeFormat "gin_template/data/time"
	"gin_template/models"
	"gin_template/services"
	"gin_template/services/dataService/robot"
	"gin_template/services/dataService/tianxing"
	"strings"
	"time"

	"go.uber.org/zap"

	//"github.com/wechaty/go-wechaty/wechaty-puppet/schemas"
	//"github.com/wechaty/go-wechaty/wechaty/user"

	"github.com/eatmoreapple/openwechat"
)

type WechatMsg struct {
	TaskId      string `json:"taskId"`
	Destination string `json:"destination,omitempty"`
	Msg         string `json:"msg,omitempty"`
}

var WechatMsgChan = make(chan *WechatMsg, 10)

// 注册微信机器人
var bot = openwechat.DefaultBot(openwechat.Desktop)

//var bot = openwechat.NewBot()

/*
	需求：通过使用微信机器人接收微信提醒订阅，如 五分钟后提醒我吃饭等
		1、需要识别语句中的时间、任务、发送者 done
		2、将数据存储入mysql，同时使用redis的过期时间以及keyspace事件通知机制来做定时	done
		3、当存入redis的定时任务过期时，将监听到的过期的定时任务放入微信发送channel
		4、通过goroutine来注册微信发送通道
		5、从微信channel中取出数据发送微信提醒
*/
// wechaty微信机器人驱动
//func RunWechatRobotByWechaty() {
//	wechaty.NewWechaty().
//		OnScan(func(ctx *wechaty.Context, qrCode string, status schemas.ScanStatus, data string) {
//			fmt.Printf("Scan QR Code to login: %s\nhttps://wechaty.github.io/qrcode/%s\n", status, qrCode)
//		}).
//		OnLogin(func(ctx *wechaty.Context, user *user.ContactSelf) {
//			fmt.Printf("User %s logined 登录成功\n", user)
//
//			//fmt.Println("找到微信机器人测试群群聊",room)
//			//room.Say("hello world")
//		}).
//		OnLogout(func(ctx *wechaty.Context, message *user.ContactSelf, reason string) {
//			fmt.Printf("Logout reason: %s\n", reason)
//		}).
//		OnMessage(func(ctx *wechaty.Context, message *user.Message) {
//			fmt.Printf("Message: %s\n", message.Text())
//			listener := message.Listener()
//			println("消息发出者", listener.Name())
//			resMsg := ""
//			room := message.Room()
//			//println("消息来自的群聊", room.Topic())
//			if room == nil { //来自个人的信息
//				resMsg = chat(message.Text(), listener.Name())
//			} else { //来自群聊的信息，需要判断是否艾特机器人
//				//room := message.Room()
//				talker := message.Talker()
//				println("消息发出者", talker.Name())
//
//				if strings.Index(message.Text(), "@钊哥哥的小号") > -1 {
//					resMsg = chat(strings.TrimSpace(strings.Replace(message.Text(), "@钊哥哥的小号", "", -1)), talker.Name())
//				}
//			}
//			message.Say(resMsg)
//
//		}).
//		DaemonStart()
//
//}

func RunWechatRobot() {
	//bot := openwechat.DefaultBot(openwechat.Desktop)
	// 注册登陆二维码回调
	bot.UUIDCallback = openwechat.PrintlnQrcodeUrl
	// 登陆
	if err := bot.Login(); err != nil {
		fmt.Println("登陆失败：", err)
		return
	}

	// 注册自动消息处理函数
	bot.MessageHandler = func(msg *openwechat.Message) {
		if msg.IsText() && msg.Content == "ping" {
			msg.ReplyText("pong")
		}
		sender, _ := msg.Sender()
		//暂时只回复文本消息
		if msg.IsText() {
			msg.ReplyText(chat(msg.Content, sender.UserName))
		}
	}
	OnCronJobMsg()
	// 阻塞主goroutine, 直到发生异常或者用户主动退出
	bot.Block()
}

func chat(content string, destUser string) string {
	res := ""
	tianxingConf := &tianxing.Config{
		Url: setting.AppConf.ApiConfig.Tianxing.Url,
		Key: setting.AppConf.ApiConfig.Tianxing.Key,
	}
	qweatherConf := &tianxing.Config{
		Url: setting.AppConf.ApiConfig.Qweather.Url,
		Key: setting.AppConf.ApiConfig.Qweather.Key,
	}
	robotConf := &tianxing.Config{
		Url: setting.AppConf.ApiConfig.Tuling.Url,
		Key: setting.AppConf.ApiConfig.Tuling.Key,
	}
	if content == "功能菜单" {
		res = "当前功能列表如下：" +
			"【1】今天天气" +
			"【2】每日情话" +
			"【3】星座运势" +
			"【4】讲个故事" +
			"【5】舔狗日记" +
			"【6】提醒服务（样例：【5】【分钟】后提醒我【睡觉】）"
	} else if content == "今天天气" { //"101200114"
		res = tianxing.RequestQweather(qweatherConf, "wuhan")
	} else if content == "每日情话" {
		res = tianxing.RequestSayLove(tianxingConf)
	} else if content == "星座运势" {
		res = tianxing.RequestStar(tianxingConf, "天蝎座")
	} else if content == "讲个故事" {
		res = tianxing.RequestStory(tianxingConf, "")
	} else if content == "舔狗日记" {
		res = tianxing.RequestDairy(tianxingConf)
	} else if strings.Index(content, "提醒我") > -1 {
		res = addRemindCronJob(content, destUser)
	} else {
		res = robot.RequestRobot(robotConf, content)
	}
	return res
}

// processWechatSend 处理微信消息发送
func processWechatSend(msgObj *WechatMsg) {
	self, err := bot.GetCurrentUser()
	if err != nil {
		fmt.Println(err)
		return
	}
	friends, err := self.Friends()
	if err != nil {
		fmt.Println(err)
		return
	}
	var dest *openwechat.Friend = nil
	for _, friend := range friends {
		if friend.UserName == msgObj.Destination {
			dest = friend
		}
	}
	//发送微信提醒消息
	zap.L().Info("目标好友", zap.Any("dest", dest))
	if dest != nil {
		currentTime := time.Now().Format(timeFormat.TimeLayoutFormat)
		remindMsg := "微信机器人提醒：请于当前时间 " + currentTime + " 进行" + msgObj.Msg
		self.SendTextToFriend(dest, remindMsg)
		// 删除对应执行任务
		zap.L().Info("删除任务", zap.String("id", msgObj.TaskId))
		services.DeleteCronTask(msgObj.TaskId)
	} else {
		zap.L().Error("用户的好友中查无此人,无法执行提醒：", zap.Any("userName", msgObj.Destination))
		fmt.Println("用户的好友中查无此人,无法执行提醒：", msgObj.Destination)
	}
}

// addRemindCronJob 添加提醒定时任务到数据库
func addRemindCronJob(content string, destUser string) string {
	zap.L().Info("提醒消息: ", zap.String("msgContent", content),
		zap.String("destFriend", destUser))
	// 样例 "【5】【分钟】后提醒我【睡觉】"
	cont := []rune(content)
	remindInfo := LettersExtractFromText(cont)
	remindInfo.RemindUser = destUser
	zap.L().Info("信息提取: ", zap.Any("msg", remindInfo))
	err := services.StoreWechatRemindCronService(remindInfo)
	if err != nil {
		zap.L().Info("定时任务数据存储失败 ", zap.Error(err))
		fmt.Println("定时任务数据存储失败", err)
	}
	return "微信机器人将会于指定时间内给您发出提醒信息"
}

// LettersExtractFromText 从微信消息中提取微信提醒任务元素
func LettersExtractFromText(text []rune) *models.RemindJobInfo {
	// "【5】【分钟】后提醒我【睡觉】"
	remindJobInfo := &models.RemindJobInfo{}
	flag := false
	var textSlice [][]rune
	var textInfoSlice []rune
	for i := 0; i < len(text); i++ {
		if text[i] == '【' {
			flag = true
			continue
		} else if text[i] == '】' {
			flag = false
			textSlice = append(textSlice, textInfoSlice)
			textInfoSlice = []rune{}
			continue
		}
		if flag {
			textInfoSlice = append(textInfoSlice, text[i])
		}
	}

	for i, runes := range textSlice {
		for _, r := range runes {
			if i == 0 {
				remindJobInfo.TimeNum += string(r)
			} else if i == 1 {
				remindJobInfo.TimeUnitByMs += string(r)
			} else {
				remindJobInfo.RemindTask += string(r)
			}
		}
	}
	zap.L().Info("信息提取逻辑", zap.Any("remindJobInfo", remindJobInfo))
	return remindJobInfo
}

func RunWechatRemindCron() {
	zap.L().Info("wechat remind Job Starting...")
	// 注册微信发送服务用于微信信息提醒
	go func() {
		for {
			select {
			case msgObj := <-WechatMsgChan:
				//发送微信提醒
				zap.L().Info("微信提醒：", zap.Any("info", msgObj))
				processWechatSend(msgObj)
			}
		}
	}()
}

func OnCronJobMsg() {
	go func() {
		msgChan := redis.Rdb.PSubscribe(redis.Ctx, redis.TOPIC).Channel()
		for {
			select {
			case msg := <-msgChan:
				{
					fmt.Println("定时任务已到期key：", msg.Payload)
					// 根据通知消息的key来查询定时任务的相关信息
					cronTask, err := services.QueryCronTask(msg.Payload)
					if err != nil {
						fmt.Println("定时任务详情查询失败", err)
					}
					WechatMsgChan <- &WechatMsg{
						TaskId:      cronTask.TaskId,
						Destination: cronTask.Reciever,
						Msg:         cronTask.Task,
					}
				}
			}
		}

	}()
}
